package com.jdone.compus.service;


import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import com.jdone.compus.enums.ConsumptionStatus;
import com.jdone.compus.enums.OrderStatus;
import com.jdone.compus.model.StudentOrder;
import com.jdone.compus.repository.StudentOrderRepository;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;


/**
 * 学生订单服务实现类。
 */
@Service
@Transactional
public class StudentOrderServiceImpl implements StudentOrderService {

    @Autowired
    private StudentOrderRepository repository;

    @Override
    public StudentOrder save(StudentOrder order) {
        return repository.save(order);
    }

    @Override
    public StudentOrder updateOrderStatusByOrderNumber(String orderNumber) {
        Optional<StudentOrder> orderOpt = repository.findByBusinessOrderNo(orderNumber);

        if (orderOpt.isPresent()) {
            StudentOrder order = orderOpt.get();
            order.setOrderStatus(OrderStatus.PAID);
            return repository.save(order);
        } else {
            throw new RuntimeException("Order not found");
        }
    }

    @Override
    public StudentOrder createOrder(StudentOrder order) {
        // 生成订单编号：当前日期 + 随机10位数字
        String orderNumber = generateOrderNumber();
        order.setBusinessOrderNo(orderNumber);

        order.setOrderStatus(OrderStatus.CREATED);
        order.setConsumptionStatus(ConsumptionStatus.PENDING);

        return repository.save(order);
    }

    private String generateOrderNumber() {
        // 获取当前日期时间，格式为yyyyMMddhhmmss
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        String dateStr = sdf.format(new Date());

        // 生成10位随机数字
        Random random = new Random();
        StringBuilder randomNumber = new StringBuilder();
        for (int i = 0; i < 10; i++) {
            randomNumber.append(random.nextInt(10));
        }

        // 拼接日期和随机数字
        return dateStr + randomNumber.toString();
    }

    @Override
    public Optional<StudentOrder> getOrderById(Long id) {
        return repository.findById(id);
    }

    @Override
    public Optional<StudentOrder> getOrderByBusinessOrderNo(String businessOrderNo) {
        return repository.findByBusinessOrderNo(businessOrderNo);
    }

    @Override
    public Iterable<StudentOrder> getOrdersByStudentId(String studentId) {
        return repository.findByStudentId(studentId);
    }

    @Override
    public StudentOrder updateOrderStatus(Long id, ConsumptionStatus status) {
        Optional<StudentOrder> orderOpt = repository.findById(id);
        if (orderOpt.isPresent()) {
            StudentOrder order = orderOpt.get();
            order.setConsumptionStatus(status);
            return repository.save(order);
        } else {
            throw new RuntimeException("Order not found");
        }
    }

    @Override
    public void deleteOrder(Long id) {
        if (repository.existsById(id)) {
            repository.deleteById(id);
        } else {
            throw new RuntimeException("Order not found");
        }
    }

    @Override
    public StudentOrder updateOrder(Long id, StudentOrder order) {
        if (repository.existsById(id)) {
            order.setOrderId(id);
            return repository.save(order);
        } else {
            throw new RuntimeException("Order not found");
        }
    }

    @Override
    public Page<StudentOrder> findOrdersByCreateTime(LocalDateTime startDate, LocalDateTime endDate, ConsumptionStatus consumptionStatus, String businessOrderNo, Pageable pageable) {
        return repository.findByCreateTimeBetween(startDate, endDate, consumptionStatus, businessOrderNo, pageable);

    }

    @Override
    public Page<StudentOrder> getOrdersByStudentIdAndDateRange(String studentId, LocalDate startDate, LocalDate endDate, Pageable pageable) {
        OrderStatus orderStatus = OrderStatus.PAID;

        if (startDate != null && endDate != null) {
            return repository.findByStudentIdAndCreateTimeBetweenAndOrderStatusOrderByCreateTimeDesc(
                    studentId, startDate.atStartOfDay(), endDate.plusDays(1).atStartOfDay(), orderStatus, pageable);
        } else if (startDate != null) {
            return repository.findByStudentIdAndCreateTimeAfterAndOrderStatusOrderByCreateTimeDesc(
                    studentId, startDate.atStartOfDay(), orderStatus, pageable);
        } else if (endDate != null) {
            return repository.findByStudentIdAndCreateTimeBeforeAndOrderStatusOrderByCreateTimeDesc(
                    studentId, endDate.plusDays(1).atStartOfDay(), orderStatus, pageable);
        } else {
            // 如果没有日期过滤条件，查询所有 PAID 状态的订单并按创建时间倒序排序
            return repository.findByStudentIdAndOrderStatusOrderByCreateTimeDesc(studentId, orderStatus, pageable);
        }
    }



    /**
     * 获取订单总数和总金额
     *
     * @param startDateTime 查询的起始时间
     * @param endDateTime 查询的结束时间
     * @return 包含订单总数和总金额的 Map
     */
    public Map<String, Object> getOrderStats(LocalDateTime startDateTime, LocalDateTime endDateTime) {
        List<Map<String, Object>> stats = repository.getOrderStats(startDateTime, endDateTime);

        Map<String, Object> result = new HashMap<>();
        if (!stats.isEmpty()) {
            result.put("orderCount", stats.get(0).get("orderCount"));
            result.put("totalAmount", stats.get(0).get("totalAmount"));
        } else {
            result.put("orderCount", 0L);
            result.put("totalAmount", 0.0);
        }
        return result;
    }


    /**
     * 导出所有订单记录为 Excel 文件
     *
     * @return 包含 Excel 文件的字节数组输入流
     * @throws IOException 如果发生输入输出错误
     */
    public ByteArrayInputStream exportAllOrdersToExcel() throws IOException {
        List<StudentOrder> orders = repository.findAll();

        try (Workbook workbook = new XSSFWorkbook(); ByteArrayOutputStream out = new ByteArrayOutputStream()) {
            Sheet sheet = workbook.createSheet("Student Orders");

            // 创建表头
            Row headerRow = sheet.createRow(0);
            headerRow.createCell(0).setCellValue("订单ID");
            headerRow.createCell(1).setCellValue("学生ID");
            headerRow.createCell(2).setCellValue("学生电话");
            headerRow.createCell(3).setCellValue("热水卡号");
            headerRow.createCell(4).setCellValue("订单金额");
            headerRow.createCell(5).setCellValue("订单状态");
            headerRow.createCell(6).setCellValue("消费状态");
            headerRow.createCell(7).setCellValue("业务订单号");
            headerRow.createCell(8).setCellValue("创建时间");
            headerRow.createCell(9).setCellValue("更新时间");

            // 填充数据行
            int rowIdx = 1;
            for (StudentOrder order : orders) {
                Row dataRow = sheet.createRow(rowIdx++);
                dataRow.createCell(0).setCellValue(order.getOrderId());
                dataRow.createCell(1).setCellValue(order.getStudentId());
                dataRow.createCell(2).setCellValue(order.getPhoneNumber());
                dataRow.createCell(3).setCellValue(order.getWaterCardNumber());
                dataRow.createCell(4).setCellValue(order.getOrderAmount());
                dataRow.createCell(5).setCellValue(order.getOrderStatus().toString());
                dataRow.createCell(6).setCellValue(order.getConsumptionStatus().toString());
                dataRow.createCell(7).setCellValue(order.getBusinessOrderNo());
                dataRow.createCell(8).setCellValue(order.getCreateTime().toString());
                dataRow.createCell(9).setCellValue(order.getUpdateTime().toString());
            }

            workbook.write(out);
            return new ByteArrayInputStream(out.toByteArray());
        }
    }

}

